#pragma once

#include <stddef.h>
#include <assert.h>
#include <string.h>

#ifndef _MSC_VER
#include <stdint.h>
#else
// visual studio has no stdint header
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;  // NOLINT
typedef unsigned short uint16_t;  // NOLINT
typedef int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
// intptr_t and friends are defined in crtdefs.h through stdio.h.
#endif

#include "checks.h"

typedef uint8_t byte;

namespace cgen {

class Cgen
{
public:
    static void FatalProcessOutOfMemory(const char * msg);
private:
    Cgen();
};

namespace internal {

#if 0
// The USE(x) template is used to silence C++ compiler warnings
// issued for (yet) unused variables (typically parameters).
template <typename T>
static inline void USE(T) { }
#else
#define USE(x)
#endif


// INLINE definition

// define used for helping GCC to make better inlining. Don't bother for debug
// builds. On GCC 3.4.5 using __attribute__((always_inline)) causes compilation
// errors in debug build.
#if defined(__GNUC__) && !defined(DEBUG)
#if (__GNUC__ >= 4)
#define INLINE(header) inline header  __attribute__((always_inline))
#else
#define INLINE(header) inline __attribute__((always_inline)) header
#endif
#else
#define INLINE(header) inline header
#endif

// constants
const int kPointerSize  = sizeof(void*);

const int KB = 1024;
const int MB = KB * KB;
const int GB = KB * KB * KB;


// typedefs
typedef byte* Address;

// FUNCTION_CAST<F>(addr) casts an address into a function
// of type F. Used to invoke generated code from within C.
template <typename F>
F FUNCTION_CAST(Address addr)
{
    return reinterpret_cast<F>(reinterpret_cast<intptr_t>(addr));
}


// arch-dependent
#if V8_HOST_ARCH_64_BIT
#ifdef _MSC_VER
#define V8_UINT64_C(x)  (x ## UI64)
#define V8_INT64_C(x)   (x ## I64)
#define V8_PTR_PREFIX "ll"
#else  // _MSC_VER
#define V8_UINT64_C(x)  (x ## UL)
#define V8_INT64_C(x)   (x ## L)
#define V8_PTR_PREFIX "l"
#endif  // _MSC_VER
#else  // V8_HOST_ARCH_64_BIT
#define V8_PTR_PREFIX ""
#endif  // V8_HOST_ARCH_64_BIT


#ifdef V8_HOST_ARCH_64_BIT
const Address kZapValue =
    reinterpret_cast<Address>(V8_UINT64_C(0xdeadbeedbeadbeed));
const Address kHandleZapValue =
    reinterpret_cast<Address>(V8_UINT64_C(0x1baddead0baddead));
const Address kFromSpaceZapValue =
    reinterpret_cast<Address>(V8_UINT64_C(0x1beefdad0beefdad));
#else
const Address kZapValue = reinterpret_cast<Address>(0xdeadbeed);
const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddead);
const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdad);
#endif


// class utility


// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName)      \
  TypeName(const TypeName&);                    \
  void operator=(const TypeName&)


// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
  TypeName();                                    \
  DISALLOW_COPY_AND_ASSIGN(TypeName)

// code

// A CodeDesc describes a buffer holding instructions and relocation
// information. The instructions start at the beginning of the buffer
// and grow forward, the relocation information starts at the end of
// the buffer and grows backward.
//
//  |<--------------- buffer_size ---------------->|
//  |<-- instr_size -->|        |<-- reloc_size -->|
//  +==================+========+==================+
//  |   instructions   |  free  |    reloc info    |
//  +==================+========+==================+
//  ^
//  |
//  buffer

class Assembler;

struct CodeDesc {
  byte* buffer;
  int buffer_size;
  int instr_size;
  int reloc_size;
  Assembler* origin;
};


}} // namespace cgen::internal
